package graphviz.parseur;

import graphviz.VisiteurGraphique;
import graphviz.MetaModel.ElementDot;
import graphviz.MetaModel.LiaisonDot;
import graphviz.MetaModel.LigneElementDot;
import graphviz.MetaModel.enumeration.TypeElementDot;
import graphviz.MetaModel.enumeration.TypeLiaisonDot;

import java.io.File;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import partager.TypeSousElement;
import partager.TypeSousElementVar;
import utils.FichierTexte;
import utils.StringUtils;
import constantes.ConstanteDot;

/**
 * permet de genrer un fichier Dot par rapport a une list de metaModelDot
 */
public class MetaModelGraphizToDot implements VisiteurGraphique
{
	private File file;
	private List<ElementDot> list;
	
	/**
	 * Constructeur par recopie
	 * @param file le fichier Dot
	 */
	public MetaModelGraphizToDot(File file)
	{
		this.file = file;
		this.list = new ArrayList<ElementDot>();
	}
	
	@Override
	public boolean ecriture()
	{
		if(file == null || list == null || list.size() == 0) return false;
		
		FichierTexte fichier = new FichierTexte(this.file);
		
/***************************************************************************************************/
/*********************la tete du fichier.***********************************************************/
/***************************************************************************************************/
		fichier.ecriture(ConstanteDot.DIAGRAMM_STRUCT);
		fichier.ecriture("{");
		fichier.ecriture(ConstanteDot.NODE);	
		
		for(int i = 0; i < list.size(); ++i)
		{
			ElementDot element = list.get(i);
			StringBuilder structure = new StringBuilder();
			
			structure.append("\t" + ConstanteDot.STRUCT);
			if(StringUtils.IsNotBank(element.getTitre())) structure.append(element.getTitre());
			else return false;
			structure.append(ConstanteDot.SHAPE_RECORD);	
			
/***************************************************************************************************/
/*********************creation des classes.*********************************************************/
/***************************************************************************************************/
			structure.append(element.getTitre());

			if(element.getType() != null && element.getType().getnum() != null && !TypeElementDot.CLASS.equals(element.getType()))
			{
				structure.append(ConstanteDot.PASSAGE_A_LA_LIGNE);
				structure.append(element.getType().getnum());
			}

			structure.append(ConstanteDot.PASSAGE_CARRER_SUIVANTE);
					
/***************************************************************************************************/
/*********************creation des variables.*******************************************************/
/***************************************************************************************************/
			if(list.get(i).getSousElement() != null)
			{
				Iterator<LigneElementDot> it = element.getSousElement().iterator();
				
				while(it.hasNext())
				{
					LigneElementDot ligne = it.next();
					
					if(TypeSousElement.ATTRIBUT.equals(ligne.getType()))
					{
						structure.append("+");
						structure.append(ligne.getNom());
						structure.append(":");
						
						if(ligne.getOutput().getList() != null && ligne.getOutput().getList())
						{
							structure.append("List\\<");
							structure.append(ligne.getOutput().getNom());
							structure.append("\\>");
						}
						else
						{
							structure.append(ligne.getOutput().getNom());
						}
						
						if(it.hasNext()) structure.append(ConstanteDot.PASSAGE_A_LA_LIGNE);
					}
				}
								
				structure.append(ConstanteDot.PASSAGE_CARRER_SUIVANTE);
				
				it = list.get(i).getSousElement().iterator();
/***************************************************************************************************/
/*********************creation des methodes.********************************************************/
/***************************************************************************************************/
				
				while(it.hasNext())
				{
					LigneElementDot ligne = it.next();
					
					if(TypeSousElement.METHODE.equals(ligne.getType()))
					{
						structure.append("+");
						structure.append(ligne.getNom());
						structure.append("(");
						if(ligne.getInput() != null && ligne.getInput().size() != 0)
						{
							Iterator<TypeSousElementVar> itSous = ligne.getInput().iterator();
							
							while(itSous.hasNext())
							{
								TypeSousElementVar sous = itSous.next();
								if(sous.getList() != null && sous.getList())
								{
									structure.append("List\\<");
									structure.append(sous.getNom());
									structure.append("\\>");
								}
								else
								{
									structure.append(sous.getNom());
								}
								
								if(itSous.hasNext()) structure.append(", ");
							}
						}
						structure.append("):");
						
						if(ligne.getOutput() != null)
						{
							if(ligne.getOutput().getList() != null && ligne.getOutput().getList())
							{
								structure.append("List\\<");
								structure.append(ligne.getOutput().getNom());
								structure.append("\\>");
							}
							else
							{
								structure.append(ligne.getOutput().getNom());
							}
						}
						else
						{
							structure.append("void");
						}
						
						
						if(it.hasNext()) structure.append(ConstanteDot.PASSAGE_A_LA_LIGNE);
					}
				}
			}
			structure.append(ConstanteDot.FIN_CLASSE);
			
			fichier.ecriture(structure.toString());	
		}		
		
		fichier.ecriture("");
		
/***************************************************************************************************/
/*********************creation des liaisons.********************************************************/
/***************************************************************************************************/

		for(int i = 0; i < list.size(); ++i)
		{
			ElementDot element = list.get(i);
			StringBuilder liaison = new StringBuilder();
			
			if(element.getLiaison() != null && element.getLiaison().size() != 0)
			{
				for(int j = 0; j < element.getLiaison().size(); ++j)
				{
					LiaisonDot liaisonDot = element.getLiaison().get(j);
					
					liaison.append(ConstanteDot.STRUCT);
					liaison.append(element.getTitre());
					if(liaisonDot.getLiaison() != null) liaison.append(liaisonDot.getLiaison().getnum());
					else liaison.append(TypeLiaisonDot.TRAIT.getnum());
					liaison.append(ConstanteDot.STRUCT);
					if(liaisonDot.getPere() != null) liaison.append(liaisonDot.getPere().getTitre());
					liaison.append(";");
					
					fichier.ecriture(liaison.toString());
				}
			}
		}

/***************************************************************************************************/
/*********************fin du fichier.***************************************************************/
/***************************************************************************************************/
		
		fichier.ecriture("}\n");	
		fichier.close();	
		
		return true;
	}

	@Override
	public boolean visite(ElementDot element) 
	{
		if(this.list == null) this.list = new ArrayList<ElementDot>();
		if(element == null) return false;
		this.list.add(element);
		return true;
	}
}
